package net.xiaosaguo.ssoserver.schedule;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * description: 定时任务
 * <p>
 * 1. 不用导入依赖，spring 已实现，启用定时任务 @EnableScheduling
 * 2. @Component
 * 3. 方法上标注 @Scheduled(cron = "* * * * * ?")
 * 4. spring 中的 cron 与 quartz 的区别：
 * -    1. 表达式由 6 位组成，秒、分、时、日、月、周，没有年
 * -    2. 周的表示：spring 中，周一到周日用 1-7 表示，quartz中，1-7 表示周日到周六，也可以写成 MON-SUN
 * 5. spring中定时任务默认是阻塞式的，如果任务执行时间比定时任务执行间隔时间长，下次任务会阻塞
 * -    1. 使用异步编排，放到统一的线程池中 : CompletableFuture.runAsync(() -> service(), threadPool);
 * -    2. 本身支持定时任务线程池,TaskSchedulingAutoConfiguration,TaskSchedulingProperties
 * -        注：spring.task.scheduling.pool.size=5，此中方式一般不起作用
 * -    3. 让定时任务异步执行,TaskExecutionAutoConfiguration,TaskExecutionProperties
 * -        spring boot 异步任务，@EnableAsync、@Async
 * -    解决方案：使用异步任务（@Async） + 定时任务（@Scheduled） 实现定时任务不阻塞执行
 *
 * @author xiaosaguo
 * @date 2020/07/19
 */
@Slf4j
@Component
@EnableScheduling
@EnableAsync
public class HelloSchedule {

    @Async
    @Scheduled(cron = "* * * * * ?")
    public void hello() {
        service();
    }

    @SneakyThrows
    private void service() {
        log.info("hello...start-" + Thread.currentThread().getId());
        Thread.sleep(3000);
        log.info("--hello...end-" + Thread.currentThread().getId());
    }
}
